golang 的 array & slice 是個很有趣的東西,接下來就直接進入正題
package main
import (
"fmt"
)
func main() {
var a [5]string
a[0] = "A"
a[1] = "B"
a[2] = "C"
a[3] = "D"
a[4] = "E"
fmt.Printf("array %#v\n", a)
}
https://play.golang.org/p/HmHwsNgE5R8
看看 Array 的示意圖
package main
import (
"fmt"
)
func main() {
var a []string
a = make([]string, 5, 5)
a[0] = "A"
a[1] = "B"
a[2] = "C"
a[3] = "D"
a[4] = "E"
fmt.Printf("array %#v\n", a)
}
// slice 需要使用 make 做初始化才能開始使用
https://play.golang.org/p/LrDLjK8sQfT
這是兩者最明顯的差別,接下來談談 Slice 內部運作的原理
首先 Slice 裡面會有三種資料型態紀錄
如果以上面 code 範例示意,他的初始化圖會像下面這樣
那我們繼續延伸一下
package main
import (
"fmt"
)
func main() {
var a []string
a = make([]string, 5, 5)
a[0] = "A"
a[1] = "B"
a[2] = "C"
a[3] = "D"
a[4] = "E"
fmt.Printf("a array %#v\n", a)
s := a[2:4]
//s[0] == "C"
//s[1] == "D"
//len(s) == 2
//cap(s) == 3
s[0] = "Z"
// a[2] == "Z" 這段是拿來證明 s是參照到 a
fmt.Printf("s array %#v\n", s)
fmt.Printf("a array %#v\n", a)
}
https://play.golang.org/p/MKojisrB5DO
Slice 切片出來的東西,都是創建一個新的Slice指向原本的Slice,所以原本的abcde slice,被切成 2-4,就會變成只有 C 跟 D,
但他的容量(cap)一開始規劃出來是 5,5-2=3,長度(len)則是 4-2=2。
Slice 有一個重點就是在於 長度(len)不可大於(cap)否則會噴錯。
我們常常需要取用某個小段的 Slice ,但 Slice 的原理都是給出參照,以上面為例,我們可能只需要 C, D 兩值,但是用 Slice 取出來卻會造成,其他 A , B , E 都一直存活著,
比較好的作法是用 copy,要如何 copy 呢,來看個範例
copy 是 buit-in function
package main
import (
"fmt"
)
func main() {
var a []string
a = make([]string, 5, 5)
a[0] = "A"
a[1] = "B"
a[2] = "C"
a[3] = "D"
a[4] = "E"
fmt.Printf("a array %#v\n", a)
s := make([]string, len(a))
copy(s, a)
s[2] = "Z"
fmt.Printf("s array %#v\n", s)
fmt.Printf("a array %#v\n", a)
}
https://play.golang.org/p/iWAA_LKyjmG